package com.bosssoft.setp.handler;

import com.bosssoft.setp.model.business.aliance.AlianceBusinessGrade;
import com.bosssoft.setp.model.business.aliance.AlianceBusinessGradeParam;
import org.springframework.stereotype.Service;
import xyz.erupt.annotation.fun.DataProxy;
import xyz.erupt.core.exception.EruptApiErrorTip;
import xyz.erupt.jpa.dao.EruptDao;

import javax.annotation.Resource;
import javax.persistence.TypedQuery;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 该类是针对 AlianceBusinessGrade 实体的数据代理类，用于在数据内容变更时进行验证。
 *
 * @author lin-gaoying
 * @version 1.0
 * @since 1.0
 */
@Service
public class AlianceBusinessGradeProxy implements DataProxy<AlianceBusinessGrade> {

    @Resource
    private EruptDao eruptDao;

    /**
     * 获取setp_aliance_business_grade表中id字段的最大值。
     *
     * @return 最大id值
     */
    private long getMaxIdFromSetpAlianceBusinessGrade() {
        List<Map<String, Object>> maps = eruptDao.getJdbcTemplate()
                .queryForList("select MAX(id) from setp_aliance_business_grade");

        if (!maps.isEmpty()) {
            Map<String, Object> firstMap = maps.get(0);
            Object maxId = firstMap.get("MAX(id)");
            if (maxId instanceof Number) {
                return ((Number) maxId).intValue();
            }
        }

        return 0L;
    }

    /**
     * 在增加AlianceBusinessGradeParam数据后调用该方法对加盟商ID数据进行自动填写。
     *
     * @param alianceBusinessGrade 待添加的AlianceBusiness实体对象
     */
    @Override
    public void afterAdd(AlianceBusinessGrade alianceBusinessGrade) {
        Set<AlianceBusinessGradeParam> params = alianceBusinessGrade.getAlianceBusinessGradeParams();
        long number = getMaxIdFromSetpAlianceBusinessGrade();

        for (AlianceBusinessGradeParam param : params) {
            param.setAlianceBusinessGradeId(number);
        }
    }

    /**
     * 在增加AlianceBusinessGrade数据前调用该方法进行手机号和邮箱的格式验证。
     * 如果手机号或邮箱格式不正确，将抛出异常提示用户。
     * 并在增加AlianceBusinessGrade数据前调用该方法对表中设备类型进行验证。
     * 如果存在相同设备类型的数据，将抛出异常提示用户。
     *
     * @param alianceBusinessGrade 待添加的AlianceBusiness实体对象
     */
    @Override
    public void beforeAdd(AlianceBusinessGrade alianceBusinessGrade) {
        BigDecimal signingFee = alianceBusinessGrade.getSigningFee();
        BigDecimal rentalFee = alianceBusinessGrade.getRentalFee();
        Set<String> set = new HashSet<>();
        Set<AlianceBusinessGradeParam> alianceBusinessGradeParams = alianceBusinessGrade.getAlianceBusinessGradeParams();

        for (AlianceBusinessGradeParam alianceBusinessGradeParam : alianceBusinessGradeParams) {
            set.add(alianceBusinessGradeParam.getParam());
        }

        if(set.size()!=alianceBusinessGradeParams.size()){
            throw new EruptApiErrorTip("表中存在相同设备类型的数据！");
        }

        if (signingFee.signum() == -1) {
            throw new EruptApiErrorTip("签约费应大于等于0");
        }

        if (rentalFee.signum() == -1) {
            throw new EruptApiErrorTip("租赁费应大于等于0");
        }

        List<AlianceBusinessGrade> list = eruptDao.lambdaQuery(AlianceBusinessGrade.class)
                .eq(AlianceBusinessGrade::getAlianceBusinessGradeName, alianceBusinessGrade.getAlianceBusinessGradeName())
                .list();
        if (!list.isEmpty()) {
            throw new EruptApiErrorTip("该等级名称已存在！");
        }

    }

    /**
     * 在修改AlianceBusinessGrade数据前调用该方法进行手机号和邮箱的格式验证。
     * 如果手机号或邮箱格式不正确，将抛出异常提示用户。
     * 并在修改AlianceBusinessGrade数据前调用该方法对表中设备类型进行验证。
     * 如果存在相同设备类型的数据，将抛出异常提示用户。
     *
     * @param alianceBusinessGrade 待添加的AlianceBusiness实体对象
     */
    @Override
    public void beforeUpdate(AlianceBusinessGrade alianceBusinessGrade) {
        BigDecimal signingFee = alianceBusinessGrade.getSigningFee();
        BigDecimal rentalFee = alianceBusinessGrade.getRentalFee();
        Set<String> set = new HashSet<>();
        Set<AlianceBusinessGradeParam> alianceBusinessGradeParams = alianceBusinessGrade.getAlianceBusinessGradeParams();

        for (AlianceBusinessGradeParam alianceBusinessGradeParam : alianceBusinessGradeParams) {
            set.add(alianceBusinessGradeParam.getParam());
        }

        if(set.size()!=alianceBusinessGradeParams.size()){
            throw new EruptApiErrorTip("表中存在相同设备类型的数据！");
        }

        if (signingFee.signum() == -1) {
            throw new EruptApiErrorTip("签约费应大于等于0");
        }

        if (rentalFee.signum() == -1) {
            throw new EruptApiErrorTip("租赁费应大于等于0");
        }

        eruptDao.getEntityManager().clear();

        String jpql = "SELECT COUNT(g) FROM AlianceBusinessGrade g "
                + "WHERE g.alianceBusinessGradeName = :name AND g.id <> :id";
        TypedQuery<Long> query = eruptDao.getEntityManager().createQuery(jpql, Long.class);
        query.setParameter("name", alianceBusinessGrade.getAlianceBusinessGradeName());
        query.setParameter("id", alianceBusinessGrade.getId());

        Long count = query.getSingleResult();
        if (count > 0) {
            throw new EruptApiErrorTip("该等级名称已存在！");
        }

    }

    /**
     * 在删除AlianceBusinessGrade数据前调用该方法进行异常处理。
     *
     * @param alianceBusinessGrade 待变更的AlianceBusiness实体对象
     */
    @Override
    public void beforeDelete(AlianceBusinessGrade alianceBusinessGrade){
        String sql = "SELECT COUNT(*) FROM setp_aliance_business WHERE aliance_business_grade_id = ?";
        Long count = eruptDao.getJdbcTemplate().queryForObject(
                sql, Long.class, alianceBusinessGrade.getId());
        if (count > 0) {
            throw new EruptApiErrorTip("删除失败！存在加盟商绑定了当前加盟商等级。");
        }
    }

}